//
// Created by pzw on 24-1-4.
// 注意我定义这几个类的顺序，顺序不对，编译出错
//
#pragma once
#ifndef CXXHANDLER_H
#define CXXHANDLER_H


#include <deque>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <functional>

/*注意我定义这几个类的顺序，顺序不对，编译出错 @{*/
class CxxHandler;

class CxxMessage;

class CxxMessageQueue;

class CxxLooper;
/*注意我定义这几个类的顺序，顺序不对，编译出错 @}*/

/* 定义函数指针类型 */
#if 0
/* 这个函数指针的泛用性有点低 */
typedef void (*MessageCallback)(CxxMessage *);
#else
/* 我们使用C++标准卡的function来定义，便于我们使用lambda表达式，简化代码操作 */
using MessageCallback = std::function<void(CxxMessage *)>;
#endif

/*1. C++ Handler @{*/
class CxxHandler {
public:
    explicit CxxHandler();

    explicit CxxHandler(CxxLooper *looper);

    virtual ~CxxHandler() = default;

    void setLooper(CxxLooper *looper);

    virtual void handleMessage(CxxMessage *msg);

    void sendMessage(CxxMessage *msg);

    void sendEmptyMessage(int what);

    void post(MessageCallback callback);

private:
    CxxLooper *mLooper;
};

/*1. C++ Handler @}*/

/* 2. C++ Message @{*/
class MessagePool {
private:
    std::vector<CxxMessage *> pool;
public:
    CxxMessage *acquire();

    void release(CxxMessage *message);
};

class CxxMessage final {
private:
    CxxMessage();

    ~CxxMessage();

    friend class MessagePool;

public:
    int what{};
    CxxHandler *handler{};
    MessageCallback callBack{};
    static MessagePool messagePool; // 对象池实例

public:
    static CxxMessage *obtain();

    static CxxMessage *obtain(int what, CxxHandler *pHandler);

    static void recycle(CxxMessage *pMessage);

};
/* 2. C++ Message @}*/

/* 3. C++ MessageQueue @{*/
class CxxMessageQueue {
public:
    CxxMessageQueue();

    ~CxxMessageQueue();

    void enQueue(CxxMessage *msg);

    CxxMessage *deQueue();

private:
    /**
     * 队列：
     * handler实现线程通信的本质模型：生产者 <---> 消费者；
     * 1. 队列还没有满的情况下，生产者向队列中添加消息；否则等待；
     * 2. 队列不为空的情况下，消费者循环从队列中取出消息；否则等待；
     */
    std::deque<CxxMessage *> msgQ{};
    /**
     * 单纯使用 std::mutex 困难之处在于，如何确定这个延时时间呢，假如生产者生产的很快，
     * 消费者却延时500ms，也不是很好，如果生产者生产的更慢，那么消费者延时500ms，还是不必要的占用了CPU。
     * ___1. 这就引出了条件变量(condition variable)，
     * ___2. c++11中提供了#include <condition_variable>头文件，
     * ___3. 其中的std::condition_variable可以和std::mutex结合一起使用，
     * ___4. 其中有两个重要的接口，notify_one()和wait()，wait()可以让线程陷入休眠状态。
     */
    std::condition_variable cond{};
    /**
     * 因此，为了性能，我们同时使用 std::condition_variable 和 std::mutex 这样性能更高。
     */
    std::mutex mutex{};
};
/* 3. C++ MessageQueue @}*/

/* 4. C++ Looper @{*/
class CxxLooper {
public:
    CxxLooper();

    ~CxxLooper();

    void enQueue(CxxMessage *msg);

    CxxMessage *deQueue();

    static void loop();

    static CxxLooper *prepare();

    static CxxLooper *getThreadLocalLooper();

private:
    CxxMessageQueue mMsgQ{};
};
/* 4. C++ Looper @}*/


#endif //CXXHANDLER_H
